package com.fulu.game.bi.service.impl.market;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.fulu.game.bi.common.util.csv.CsvExportUtil;
import com.fulu.game.bi.common.util.csv.Mapper;
import com.fulu.game.bi.common.util.csv.Querier;
import com.fulu.game.bi.entity.enums.QueryTypeStatusEnum;
import com.fulu.game.bi.entity.po.market.HistoryTrendStat;
import com.fulu.game.bi.entity.vo.market.CommonlyQueryVO;
import com.fulu.game.bi.entity.vo.market.HistoryTrendStatVO;
import com.fulu.game.bi.mysql.bi.market.HistoryTrendStatDao;
import com.fulu.game.bi.redis.service.market.HistoryTrendStatService;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class HistoryTrendStatServiceImpl implements HistoryTrendStatService {

    @Autowired
    private HistoryTrendStatDao historyTrendStatDao;

    @Autowired
    private CommonlyStatService commonlyStatService;

    public static final Map<Integer, String> tableNameMap = new HashMap() {
        {
            put(QueryTypeStatusEnum.DAY.getType(), "t_history_trend_stat_day");
            put(QueryTypeStatusEnum.WEEK.getType(), "t_history_trend_stat_week");
            put(QueryTypeStatusEnum.MONTH.getType(), "t_history_trend_stat_month");

        }
    };

    @Override
    public List<HistoryTrendStat> list(CommonlyQueryVO vo) {
        return commonlyStatService.list(vo, tableNameMap, () -> historyTrendStatDao.list(vo));
    }

    @Override
    public HistoryTrendStatVO yesterday() {
        CommonlyQueryVO commonlyQueryVO = new CommonlyQueryVO();
        commonlyQueryVO.setStatTimeStart(DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -1)));
        commonlyQueryVO.setStatTimeEnd(DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -1)));
        commonlyQueryVO.setQueryType(QueryTypeStatusEnum.DAY.getType());
        commonlyQueryVO.setTableName(tableNameMap.get(QueryTypeStatusEnum.DAY.getType()));
        List<HistoryTrendStat> yesterday = list(commonlyQueryVO);
        HistoryTrendStat yesterdayStat = CollectionUtil.isEmpty(yesterday) ? init() : yesterday.get(0);
        commonlyQueryVO.setStatTimeStart(DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -2)));
        commonlyQueryVO.setStatTimeEnd(DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -2)));
        List<HistoryTrendStat> dayBeforeYesterday = list(commonlyQueryVO);
        HistoryTrendStat dayBeforeYesterdayStat = CollectionUtil.isEmpty(dayBeforeYesterday) ? init() : dayBeforeYesterday.get(0);
        commonlyQueryVO.setStatTimeStart(DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -8)));
        commonlyQueryVO.setStatTimeEnd(DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -8)));
        List<HistoryTrendStat> sameWeekDayWithYesterday = list(commonlyQueryVO);
        HistoryTrendStat sameWeekDayWithYesterdayStat = CollectionUtil.isEmpty(sameWeekDayWithYesterday) ? init() : sameWeekDayWithYesterday.get(0);
        HistoryTrendStatVO historyTrendStatVO = new HistoryTrendStatVO();
        historyTrendStatVO.setLivelyUserNum(yesterdayStat.getLivelyUserNum());
        historyTrendStatVO.setLivelyUserNumDay(datioForInteger(yesterdayStat.getLivelyUserNum(), dayBeforeYesterdayStat.getLivelyUserNum()));
        historyTrendStatVO.setLivelyUserNumWeek(datioForInteger(yesterdayStat.getLivelyUserNum(), sameWeekDayWithYesterdayStat.getLivelyUserNum()));
        historyTrendStatVO.setInvestUserAll(yesterdayStat.getInvestUserAll());
        historyTrendStatVO.setInvestUserAllDay(datioForInteger(yesterdayStat.getInvestUserAll(), dayBeforeYesterdayStat.getInvestUserAll()));
        historyTrendStatVO.setInvestUserAllWeek(datioForInteger(yesterdayStat.getInvestUserAll(), sameWeekDayWithYesterdayStat.getInvestUserAll()));
        historyTrendStatVO.setConsumeUserAll(yesterdayStat.getConsumeUserAll());
        historyTrendStatVO.setConsumeUserAllDay(datioForInteger(yesterdayStat.getConsumeUserAll(), dayBeforeYesterdayStat.getConsumeUserAll()));
        historyTrendStatVO.setConsumeUserAllWeek(datioForInteger(yesterdayStat.getConsumeUserAll(), sameWeekDayWithYesterdayStat.getConsumeUserAll()));
        historyTrendStatVO.setOrderUserNum(yesterdayStat.getOrderUserNum());
        historyTrendStatVO.setOrderUserNumDay(datioForInteger(yesterdayStat.getOrderUserNum(), dayBeforeYesterdayStat.getOrderUserNum()));
        historyTrendStatVO.setOrderUserNumWeek(datioForInteger(yesterdayStat.getOrderUserNum(), sameWeekDayWithYesterdayStat.getOrderUserNum()));
        historyTrendStatVO.setInvestMoneyAll(yesterdayStat.getInvestMoneyAll());
        historyTrendStatVO.setInvestMoneyAllDay(datioForBigDecimal(yesterdayStat.getInvestMoneyAll(), dayBeforeYesterdayStat.getInvestMoneyAll()));
        historyTrendStatVO.setInvestMoneyAllWeek(datioForBigDecimal(yesterdayStat.getInvestMoneyAll(), sameWeekDayWithYesterdayStat.getInvestMoneyAll()));
        historyTrendStatVO.setPipiMoneyInvestAll(yesterdayStat.getPipiMoneyInvestAll());
        historyTrendStatVO.setPipiMoneyInvestAllDay(datioForBigDecimal(yesterdayStat.getPipiMoneyInvestAll(), dayBeforeYesterdayStat.getPipiMoneyInvestAll()));
        historyTrendStatVO.setPipiMoneyInvestAllWeek(datioForBigDecimal(yesterdayStat.getPipiMoneyInvestAll(), sameWeekDayWithYesterdayStat.getPipiMoneyInvestAll()));
        historyTrendStatVO.setVirtualMoneyInvestAll(yesterdayStat.getVirtualMoneyInvestAll());
        historyTrendStatVO.setVirtualMoneyInvestAllDay(datioForBigDecimal(yesterdayStat.getVirtualMoneyInvestAll(), dayBeforeYesterdayStat.getVirtualMoneyInvestAll()));
        historyTrendStatVO.setVirtualMoneyInvestAllWeek(datioForBigDecimal(yesterdayStat.getVirtualMoneyInvestAll(), sameWeekDayWithYesterdayStat.getVirtualMoneyInvestAll()));
        historyTrendStatVO.setInvestNum(yesterdayStat.getInvestNum());
        historyTrendStatVO.setInvestNumDay(datioForInteger(yesterdayStat.getInvestNum(), dayBeforeYesterdayStat.getInvestNum()));
        historyTrendStatVO.setInvestNumWeek(datioForInteger(yesterdayStat.getInvestNum(), sameWeekDayWithYesterdayStat.getInvestNum()));
        historyTrendStatVO.setConsumeMoneyAll(yesterdayStat.getConsumeMoneyAll());
        historyTrendStatVO.setConsumeMoneyAllDay(datioForBigDecimal(yesterdayStat.getConsumeMoneyAll(), dayBeforeYesterdayStat.getConsumeMoneyAll()));
        historyTrendStatVO.setConsumeMoneyAllWeek(datioForBigDecimal(yesterdayStat.getConsumeMoneyAll(), sameWeekDayWithYesterdayStat.getConsumeMoneyAll()));
        historyTrendStatVO.setPipiMoneyConsumeAll(yesterdayStat.getPipiMoneyConsumeAll());
        historyTrendStatVO.setPipiMoneyConsumeAllDay(datioForBigDecimal(yesterdayStat.getPipiMoneyConsumeAll(), dayBeforeYesterdayStat.getPipiMoneyConsumeAll()));
        historyTrendStatVO.setPipiMoneyConsumeAllWeek(datioForBigDecimal(yesterdayStat.getPipiMoneyConsumeAll(), sameWeekDayWithYesterdayStat.getPipiMoneyConsumeAll()));
        historyTrendStatVO.setVirtualMoneyConsumeAll(yesterdayStat.getVirtualMoneyConsumeAll());
        historyTrendStatVO.setVirtualMoneyConsumeAllDay(datioForBigDecimal(yesterdayStat.getVirtualMoneyConsumeAll(), dayBeforeYesterdayStat.getVirtualMoneyConsumeAll()));
        historyTrendStatVO.setVirtualMoneyConsumeAllWeek(datioForBigDecimal(yesterdayStat.getVirtualMoneyConsumeAll(), sameWeekDayWithYesterdayStat.getVirtualMoneyConsumeAll()));
        historyTrendStatVO.setConsumeNum(yesterdayStat.getConsumeNum());
        historyTrendStatVO.setConsumeNumDay(datioForInteger(yesterdayStat.getConsumeNum(), dayBeforeYesterdayStat.getConsumeNum()));
        historyTrendStatVO.setConsumeNumWeek(datioForInteger(yesterdayStat.getConsumeNum(), sameWeekDayWithYesterdayStat.getConsumeNum()));
        return historyTrendStatVO;
    }

    public HistoryTrendStat init() {
        HistoryTrendStat historyTrendStat = new HistoryTrendStat();
        historyTrendStat.setLivelyUserNum(0);
        historyTrendStat.setInvestUserAll(0);
        historyTrendStat.setConsumeUserAll(0);
        historyTrendStat.setOrderUserNum(0);
        historyTrendStat.setInvestMoneyAll(BigDecimal.ZERO);
        historyTrendStat.setPipiMoneyInvestAll(BigDecimal.ZERO);
        historyTrendStat.setVirtualMoneyInvestAll(BigDecimal.ZERO);
        historyTrendStat.setInvestNum(0);
        historyTrendStat.setConsumeMoneyAll(BigDecimal.ZERO);
        historyTrendStat.setPipiMoneyConsumeAll(BigDecimal.ZERO);
        historyTrendStat.setVirtualMoneyConsumeAll(BigDecimal.ZERO);
        historyTrendStat.setConsumeNum(0);
        return historyTrendStat;
    }

    private BigDecimal datioForBigDecimal(BigDecimal a, BigDecimal b) {
        if (b.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        return a.subtract(b).divide(b, 2, BigDecimal.ROUND_HALF_DOWN);
    }

    private BigDecimal datioForInteger(Integer a, Integer b) {
        return datioForBigDecimal(BigDecimal.valueOf(a), BigDecimal.valueOf(b));
    }


    @Override
    public void export(CommonlyQueryVO vo) {
        LinkedHashMap<String, Mapper<HistoryTrendStat>> map = new LinkedHashMap<>();

        String fileName = "历史趋势" + vo.getStatTimeStart() + "-" + vo.getStatTimeEnd();

        map.put("日期", v -> v.getBeginStatDay() + "-" + v.getEndStatDay());
        map.put("渠道分组", v -> v.getSourceGroupName());
        map.put("渠道来源", v -> v.getSourceName());
        map.put("标签分组", v -> v.getLabelGroupName());
        map.put("标签", v -> v.getLabelName());
        map.put("系统", v -> v.getRegisterTypeName());

        map.put("活跃用户数", v -> v.getLivelyUserNum() + "");
        map.put("新用户数", v -> v.getNewRegistUserNum() + "");
        map.put("活跃老用户数", v -> v.getLivelyOldUserNum() + "");

        map.put("充值总金额", v -> v.getInvestMoneyAll() + "");
        map.put("充值总次数", v -> v.getInvestNum() + "");
        map.put("充值总人数", v -> v.getInvestUserAll() + "");

        map.put("消费总金额", v -> v.getConsumeMoneyAll() + "");
        map.put("消费总次数", v -> v.getConsumeNum() + "");
        map.put("消费总人数", v -> v.getConsumeUserAll() + "");

        map.put("皮皮币充值金额", v -> v.getPipiMoneyInvestAll() + "");
        map.put("皮皮币充值次数", v -> v.getPipiMoneyInvestNum() + "");
        map.put("皮皮币充值人数", v -> v.getPipiMoneyInvestUserNum() + "");

        map.put("钻石充值金额", v -> v.getVirtualMoneyInvestAll() + "");
        map.put("钻石充值次数", v -> v.getVirtualMoneyInvestNum() + "");
        map.put("钻石充值人数", v -> v.getVirtualMoneyInvestUserNum() + "");

        map.put("皮皮币消费金额", v -> v.getPipiMoneyConsumeAll() + "");
        map.put("皮皮币消费次数", v -> v.getPipiMoneyConsumeNum() + "");
        map.put("皮皮币消费人数", v -> v.getPipiMoneyConsumeUserNum() + "");

        map.put("钻石消费金额", v -> v.getVirtualMoneyConsumeAll() + "");
        map.put("钻石消费次数", v -> v.getVirtaulMoneyConsumeNum() + "");
        map.put("钻石消费人数", v -> v.getVirtualMoneyConsumeUserNum() + "");

        map.put("订单支付金额", v -> v.getOrderMoneyAll() + "");
        map.put("订单支付次数", v -> v.getOrderNum() + "");
        map.put("订单支付人数", v -> v.getOrderUserNum() + "");

        map.put("订单退款次数", v -> v.getRefundNum() + "");
        map.put("订单退款人数", v -> v.getRefundUserNum() + "");
        map.put("优惠券退款金额", v -> v.getRefundCouponMoneyAll() + "");

        map.put("优惠券使用金额", v -> v.getCouponMoneyAll() + "");
        map.put("订单退款金额", v -> v.getRefundMoneyAll() + "");


        Querier querier = (num) -> {
            List<HistoryTrendStat> list = list(vo);
            PageInfo pageInfo = new PageInfo(list);
            pageInfo.setHasNextPage(false);
            return pageInfo;
        };

        CsvExportUtil.export(100, fileName, map, querier);
    }
}
